import Vue from 'vue';
import Axios from 'axios';
import qs from 'qs';

let sessionTicket = '';
let getSessionTicketUrl = '/__local/basic%5Ccreate_session_ticket';
let gettingSessionTicket = false;
let getSessionTicketTimes = 0;

// Axios.defaults['withCredentials'] = true;

// H5端访问地址$studentBaseUrl 商家端访问地址$shopBaseUrl  请求地址$baseUrl
switch (window.location.host) {
    // 生产环境
    case 'phaadmin.wxhand.com':
        Vue.prototype.$studentBaseUrl = 'http://student.zsdx.cn';
        Vue.prototype.$shopBaseUrl = 'http://cms.zsdx.cn';
        Vue.prototype.$baseUrl = BASE_URL;
        break;
    // 预发布环境
    case 'phaadmin.pre.wxhand.com':
        Vue.prototype.$studentBaseUrl = 'http://student.pre.zsdx.cn';
        Vue.prototype.$shopBaseUrl = 'http://cms.pre.zsdx.cn';
        Vue.prototype.$baseUrl = BASE_URL_PRE;
        break;
    // 开发环境
    default:
        Vue.prototype.$studentBaseUrl = 'http://student-dev.wxhand.com';
        Vue.prototype.$shopBaseUrl = 'http://gt.wxhand.com';
        Vue.prototype.$baseUrl = BASE_URL_DEV;
        break;
}

let axios = Axios.create({
    baseURL: Vue.prototype.$baseUrl,
    // baseURL: window.location.host == 'phaadmin.wxhand.com' ? 'phaadmin.wxhand.com' : 'phaadmin-api.wxhand.com',
    transformRequest: [function (data, headers) {
        var resData = data;

        if (!(resData instanceof FormData)) {
            resData = qs.stringify(resData);
        }
        return resData;
    }],
    method: 'post'
});

axios.interceptors.request.use(function (config) { // 这里的config包含每次请求的内容
    // 上传文件到又拍云不允许加header
    if(config.url.indexOf('api.upyun.com') < 0) {
        config.headers['zsdx-session-ticket'] = sessionTicket;
    }
    return config;
}, function (err) {
    return Promise.reject(err);
});

axios.defaults.retry = 3;
axios.defaults.retryDelay = 1000;
axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
    var config = err.config;
    // 如果config不存在或未设置重试选项，请拒绝

    if(!config || !config.retry) return Promise.reject(err);
    // 设置变量跟踪重试次数
    config.__retryCount = config.__retryCount || 0;
    // 检查是否已经达到最大重试总次数
    if(config.__retryCount >= config.retry) {
        // 抛出错误信息
        return Promise.reject(err);
    }
    // 增加请求重试次数
    config.__retryCount += 1;
    // 创建新的异步请求
    var backoff = new Promise(function(resolve) {
        setTimeout(function() {
            resolve();
        }, config.retryDelay || 1);
    });
    // 返回axios信息，重新请求

    return backoff.then(function() {
        return axios(config);
    });
});

function getSessionTicketLocal() {
    if (!sessionTicket) {
        sessionTicket = localStorage.sessionTicket;
    }

    return sessionTicket;
}

/** 向服务器索取新的sessionTicket */
function getSessionTicketRemote(callback) {
    if (getSessionTicketTimes > 10) {
        Vue.prototype.$notify.error({
            title: '错误',
            message: '服务器错误，请稍后重试'
        });
        return;
    }
    gettingSessionTicket = true;
    axios.post(getSessionTicketUrl, {}).then(function (response) {
        if (response.status != '200') {
            return Promise.reject(res);
        }
        let resp = response.data;

        if (resp.code == 1) {
            // 重置请求次数
            getSessionTicketTimes = 0;
            sessionTicket = resp.data.session_ticket;
            // 本地存储
            localStorage.sessionTicket = sessionTicket;
        }
        gettingSessionTicket = false;
        getSessionTicketTimes++;
        if (callback) {
            callback(sessionTicket);
        }
    }).catch(function (err) {
        gettingSessionTicket = false;
        getSessionTicketTimes++;
        return Promise.reject(err);
    });
}

/** 获取sessiongTicket */
function getSessionTicket(callback) {
    let st = '';

    if (gettingSessionTicket) {
        setTimeout(function () {
            callback('');
        }, 200);
        return;
    }
    st = getSessionTicketLocal();
    if (st) {
        callback(st);
    } else {
        getSessionTicketRemote(function (st) {
            callback(st);
        });
    }
}
/**
 * 处理请求返回结果
 * @param resp axios返回原始数据,
 * @param instance 调用接口原始vue实例
 */
function dealResponse(resp, options) {
    if (resp.status != '200') {
        return Promise.reject(res);
    }

    let instance = options.instance;

    // sessionTicket缺失或者失效
    if (resp.data.code == 1001) {
        if (gettingSessionTicket) {
            setTimeout(function () {
                instance.$post(options.url, options.data, options.success, options.fail);
            }, 200);
            return;
        }
        getSessionTicketRemote(function (currTicket) {
            instance.$post(options.url, options.data, options.success, options.fail, currTicket);
        });
        return;
    }

    // 未登录
    if (resp.data.code == 1002) {
        instance.$router.push({
            name: 'Login',
            params: {
                dist: {
                    path: instance.$route.path,
                    query: instance.$route.query
                }
            }
        });
        return;
    }

    // 没有授权
    if (resp.data.code == 1003) {
        instance.$router.push({
            name: 'NoAuth'
        });
        return;
    }

    //帐号已在其它设备登录
    if (resp.data.code == 1004) {
        instance.$router.replace({
            path: '/Login?only=true'
        });
        return;
    }

    if (options.success) {
        options.success(resp.data);
    }
}

/** 清除客户端保留sessionTicket */
function clearSessionTicket() {
    if (sessionTicket == localStorage.sessionTicket) {
        localStorage.sessionTicket = undefined;
    }
    sessionTicket = undefined;
}
/** 手动设置sessionTicket */
function setSessionTicket(ticket) {
    sessionTicket = ticket;
    // 本地存储 防止出现覆盖管理员身份,只是保存临时变量,刷新丢失
    localStorage.sessionTicket = ticket;
}

/**
 * 一般post请求
 * @param
 */
function post(url, data, success, fail, session_ticket) {
    let instance = this;
    let st = session_ticket;

    if (!st && url != getSessionTicketUrl) {
        getSessionTicket(function (currTicket) {
            instance.$post(url, data, success, fail, currTicket);
        });
    } else {
        axios.post(url, data)
            .then(function (resp) {
                dealResponse(resp, {
                    instance,
                    url,
                    data,
                    success,
                    fail
                });
            })
            .catch(function (err) {
                if (fail) {
                    fail(err);
                }
                return Promise.reject(err);
            });
    }

}

/**
 * 上传文件请求
 * @param options 请求相关配置{url, data, progress(上传进度), success, fail}
 * @param session_ticket ticket
 */
function upload(options, session_ticket) {
    let instance = this;
    let st = session_ticket;

    if (!st && options.url != getSessionTicketUrl) {
        getSessionTicket(function (currTicket) {
            instance.$upload(options, currTicket);
        });
    } else {
        axios.post(options.url, options.data, {
            onUploadProgress: function (e) {
                if (e.total > 0) {
                    e.percent = e.loaded / e.total * 100;
                }
                if (options.progress) {
                    options.progress(e);
                }
            }
        }).then(function (resp) {
            dealResponse(resp, {
                instance,
                url: options.url,
                data: options.data,
                success: options.success,
                fail: options.success
            });
        }).catch(function (err) {
            if (options.fail) {
                options.fail(err);
            }
            return Promise.reject(err);
        });
    }

}

function install(Vue, options) {
    Vue.axios = Axios;

    Object.defineProperties(Vue.prototype, {
        $post: {
            get() {
                return post.bind(this);
            }
        },
        $upload: {
            get() {
                return upload.bind(this);
            }
        },
        axios: {
            get() {
                return axios;
            }
        },
        clearSessionTicket: {
            get() {
                return clearSessionTicket;
            }
        },
        setSessionTicket: {
            get() {
                return setSessionTicket;
            }
        }
    });
}

export default {
    install
};
